package com.tms.gateway.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

@Component
public class GlobalFilter implements org.springframework.cloud.gateway.filter.GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(GlobalFilter.class);
    
    private final AntPathMatcher pathMatcher = new AntPathMatcher();
    
    @Autowired
    private RestTemplate restTemplate;
    
    // 白名单路径，这些路径不需要验证权限
    private final List<String> whiteList = Arrays.asList(
            "/userLogin/login",
            "/basic/register",
            "/auth/oauth/token",
            "/auth/auth/login",
            "/auth/rsa/publicKey",
            "/*/v3/api-docs",
            "/*/swagger-ui.html",
            "/*/swagger-resources/**",
            "/*/webjars/**",
            "/*/druid/**"
    );

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        String method = request.getMethod().name();
        
        log.info("请求: {} {}", method, path);
        
        // 白名单路径直接放行
        if (isWhitePath(path)) {
            return chain.filter(exchange);
        }
        
        // 获取请求头中的token
        String token = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        
        // 如果token为空，返回未授权错误
        if (!StringUtils.hasText(token)) {
            return unauthorizedResponse(exchange, "令牌不能为空");
        }
        
        // 如果token不是以Bearer开头，添加Bearer前缀
        if (!token.startsWith("Bearer ")) {
            token = "Bearer " + token;
        }
        
        try {
            // 调用auth服务验证token
            boolean isValid = validateToken(token);
            if (!isValid) {
                return unauthorizedResponse(exchange, "令牌验证失败");
            }
            
            // 将token传递给下游服务
            ServerHttpRequest mutatedRequest = request.mutate()
                    .header(HttpHeaders.AUTHORIZATION, token)
                    .build();
            
            return chain.filter(exchange.mutate().request(mutatedRequest).build())
                    .then(Mono.fromRunnable(() -> {
                        log.info("响应: {} {}", method, path);
                    }));
        } catch (Exception e) {
            log.error("处理令牌时发生错误", e);
            return unauthorizedResponse(exchange, "令牌处理异常");
        }
    }
    
    private boolean isWhitePath(String path) {
        return whiteList.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }
    
    private boolean validateToken(String token) {
        // 调用auth服务验证token
        try {
            // 实际项目中应该使用Feign或WebClient调用auth服务
            String result = restTemplate.getForObject("http://tms-auth/oauth/check_token?token=" + token.replace("Bearer ", ""), String.class);
            return result != null && !result.contains("error");
        } catch (Exception e) {
            log.error("验证令牌时发生错误", e);
            return false;
        }
    }
    
    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        
        String body = "{\"code\":401,\"msg\":\"" + msg + "\"}";
        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
        
        return response.writeWith(Mono.just(buffer));
    }

    @Override
    public int getOrder() {
        return -1;
    }
}